#ifndef __CG_API_H__
#define __CG_API_H__

typedef struct
{
	// print message on the local console
	void		(*Print)( const char *fmt );

	// abort the game
	void		(*Error)( const char *fmt );

	// milliseconds should only be used for performance tuning, never
	// for anything game related.  Get time from the CG_DrawActiveFrame parameter
	int			(*Milliseconds)( void );

	// console variable interaction
	void		(*Cvar_Register)( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags );
	void		(*Cvar_Update)( vmCvar_t *vmCvar );
	void		(*Cvar_Set)( const char *var_name, const char *value );
	void		(*Cvar_VariableStringBuffer)( const char *var_name, char *buffer, int bufsize );

	// ServerCommand and ConsoleCommand parameter access
	int			(*Argc)( void );
	void		(*Argv)( int n, char *buffer, int bufferLength );
	void		(*Args)( char *buffer, int bufferLength );

	// filesystem access
	// returns length of file
	int			(*FS_FOpenFile)( const char *qpath, fileHandle_t *f, fsMode_t mode );
	int			(*FS_Read)( void *buffer, int len, fileHandle_t f );
	int			(*FS_Write)( const void *buffer, int len, fileHandle_t f );
	void		(*FS_FCloseFile)( fileHandle_t f );
	int			(*FS_Seek)( fileHandle_t f, long offset, int origin ); // fsOrigin_t

	// add commands to the local console as if they were typed in
	// for map changing, etc.  The command is not executed immediately,
	// but will be executed in order the next time console commands
	// are processed
	void		(*SendConsoleCommand)( const char *text );

	// register a command name so the console can perform command completion.
	// FIXME: replace this with a normal console command "defineCommand"?
	void		(*AddCommand)( const char *cmdName );

	void		(*RemoveCommand)( const char *cmdName );

	// send a string to the server over the network
	void		(*SendClientCommand)( const char *s );

	// Similar to above, but may be interleaved within movements
	void		(*SendTimedClientCommand)( const char *text );

	// force a screen update, only used during gamestate load
	void		(*UpdateScreen)( void );

	// model collision
	void		(*CM_LoadMap)( const char *mapname );
	int			(*CM_NumInlineModels)( void );
	clipHandle_t (*CM_InlineModel)( int index );		// 0 = world, 1+ = bmodels
	clipHandle_t (*CM_TempBoxModel)( const vec3_t mins, const vec3_t maxs );
	int			(*CM_PointContents)( const vec3_t p, clipHandle_t model );
	int			(*CM_TransformedPointContents)( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles );
	void		(*CM_BoxTrace)( trace_t *results, const vec3_t start, const vec3_t end,
						  const vec3_t mins, const vec3_t maxs,
						  clipHandle_t model, int brushmask );
	void		(*CM_TransformedBoxTrace)( trace_t *results, const vec3_t start, const vec3_t end,
						  const vec3_t mins, const vec3_t maxs,
						  clipHandle_t model, int brushmask,
						  const vec3_t origin, const vec3_t angles );

	// Returns the projection of a polygon onto the solid brushes in the world
	int			(*CM_MarkFragments)( int numPoints, const vec3_t *points, 
				const vec3_t projection,
				int maxPoints, vec3_t pointBuffer,
				int maxFragments, markFragment_t *fragmentBuffer );

	// normal sounds will have their volume dynamically changed as their entity
	// moves and the listener moves
	void		(*S_StartSound)( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx );
	void		(*S_StopLoopingSound)(int entnum);

	// a local sound is always played full volume
	void		(*S_StartLocalSound)( sfxHandle_t sfx, int channelNum );
	void		(*S_ClearLoopingSounds)( qboolean killall );
	void		(*S_AddLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
	void		(*S_AddRealLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
	void		(*S_UpdateEntityPosition)( int entityNum, const vec3_t origin );

	// respatialize recalculates the volumes of sound as they should be heard by the
	// given entityNum and position
	void		(*S_Respatialize)( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
	sfxHandle_t	(*S_RegisterSound)( const char *sample, qboolean compressed );		// returns buzz if not found
	void		(*S_StartBackgroundTrack)( const char *intro, const char *loop );	// empty name stops music
	void	(*S_StopBackgroundTrack)( void );


	void		(*R_LoadWorldMap)( const char *mapname );

	// all media should be registered during level startup to prevent
	// hitches during gameplay
	qhandle_t	(*R_RegisterModel)( const char *meshName, const char *skelName );			// returns rgb axis if not found
	qhandle_t	(*R_RegisterSkin)( const char *name );			// returns all white if not found
	qhandle_t	(*R_RegisterShader)( const char *name );			// returns all white if not found
	qhandle_t	(*R_RegisterShaderNoMip)( const char *name );			// returns all white if not found

	// a scene is built up by calls to R_ClearScene and the various R_Add functions.
	// Nothing is drawn until R_RenderScene is called.
	void		(*R_ClearScene)( void );
	void		(*R_AddRefEntityToScene)( const refEntity_t *re );

	// polys are intended for simple wall marks, not really for doing
	// significant construction
	void		(*R_AddPolysToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys );
	void		(*R_AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b );
	int			(*R_LightForPoint)( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
	void		(*R_RenderScene)( const refdef_t *fd );
	void		(*R_SetColor)( const float *rgba );	// NULL = 1,1,1,1
	void		(*R_DrawStretchPic)( float x, float y, float w, float h, 
				float s1, float t1, float s2, float t2, qhandle_t hShader );
	void		(*R_ModelBounds)( clipHandle_t model, vec3_t mins, vec3_t maxs );
	int			(*R_LerpTag)( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame, 
						   float frac, const char *tagName );
	void		(*R_RemapShader)( const char *oldShader, const char *newShader, const char *timeOffset );

	// The glconfig_t will not change during the life of a cgame.
	// If it needs to change, the entire cgame will be restarted, because
	// all the qhandle_t are then invalid.
	void		(*GetGlconfig)( glconfig_t *glconfig );

	// the gamestate should be grabbed at startup, and whenever a
	// configstring changes
	void		(*GetGameState)( gameState_t *gamestate );

	// cgame will poll each frame to see if a newer snapshot has arrived
	// that it is interested in.  The time is returned seperately so that
	// snapshot latency can be calculated.
	void		(*GetCurrentSnapshotNumber)( int *snapshotNumber, int *serverTime );

	// a snapshot get can fail if the snapshot )(or the entties it holds) is so
	// old that it has fallen out of the client system queue
	qboolean	(*GetSnapshot)( int snapshotNumber, snapshot_t *snapshot );

	// retrieve a text command from the server stream
	// the current snapshot will hold the number of the most recent command
	// qfalse can be returned if the client system handled the command
	// argc)() / argv)() can be used to examine the parameters of the command
	qboolean	(*GetServerCommand)( int serverCommandNumber );

	// returns the most recent command number that can be passed to GetUserCmd
	// this will always be at least one higher than the number in the current
	// snapshot, and it may be quite a few higher if it is a fast computer on
	// a lagged connection
	int			(*GetCurrentCmdNumber)( void );	

	qboolean	(*GetUserCmd)( int cmdNumber, usercmd_t *ucmd );

	// used for the weapon select and zoom
	void		(*SetUserCmdValue)( int stateValue, float sensitivityScale );

	int			(*MemoryRemaining)( void );
	void		(*R_RegisterFont)(const char *fontName, int pointSize, fontInfo_t *font);
	qboolean	(*Key_IsDown)( int keynum );
	int			(*Key_GetCatcher)( void );
	void		(*Key_SetCatcher)( int catcher );
	int			(*Key_GetKey)( const char *binding );

	int			(*PC_ReadToken)( int handle, pc_token_t *pc_token );
	int			(*PC_SourceFileAndLine)( int handle, char *filename, int *line );

	void		(*Sys_SnapVector)( float *v );

	// Riot - Asset loader cycling
	void		(*R_WaitForLoader) ( void );
} cgameImports_t;

typedef struct
{
	void (*Init)( int serverMessageNum, int serverCommandSequence, int clientNum );
	void (*Shutdown)();
	qboolean (*ConsoleCommand)();
	void (*DrawActiveFrame)( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback );
	int (*CrosshairPlayer)();
	int (*LastAttacker)();
	void (*KeyEvent)(int key, qboolean down);
	void (*MouseEvent)(int x, int y);
	void (*EventHandling)(int arg);
} cgameExports_t;

#endif
